
package cz.czu.pef.DataModelling.tests.data.prepare;

import java.util.*;
import java.util.logging.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.annotation.Transactional;

import cz.czu.pef.DataModelling.*;
import cz.czu.pef.DataModelling.domainObjects.*;
import cz.czu.pef.DataModelling.service.api.*;
import cz.czu.pef.DataModelling.tests.data.BasicData;
import cz.czu.pef.DataModelling.utils.Constants;


@Component(value = "prepareGardeningData")
@SuppressWarnings("unused")
@ContextConfiguration(locations = {Constants.springTestingClasspathConfig})
public class PrepareGardeningData extends BasicData
{

  Logger logger = Logger.getLogger(PrepareGardeningData.class.getName());
  @Autowired protected PrepareSharedData prepareSharedData;

  public void fillBasicData()
  {
    // ##############################################
    // EXISTING OBJECTS
    // ##############################################

    MedicalExaminationType medExam_Praktik = medicalExaminationTypeService.findByAttributeUniqueResult("code", Constants.MEDICAL_EXAMINATION_TYPE_PRAKTIK);
    MedicalExaminationType medExam_Ocni = medicalExaminationTypeService.findByAttributeUniqueResult("code", Constants.MEDICAL_EXAMINATION_TYPE_OCNI);
    MedicalExaminationType medExam_Neurolog = medicalExaminationTypeService.findByAttributeUniqueResult("code", Constants.MEDICAL_EXAMINATION_TYPE_NEURO);
    MedicalExaminationType medExam_Psycholog = medicalExaminationTypeService.findByAttributeUniqueResult("code", Constants.MEDICAL_EXAMINATION_TYPE_PSYCHO);
    if (medExam_Praktik == null || medExam_Ocni == null || medExam_Neurolog == null || medExam_Psycholog == null)
      throw new RuntimeException("Some MedicalExaminationType is missing!");

    TrainingType training_BOZP = trainingTypeService.findByAttributeUniqueResult("code", Constants.TRAINING_TYPE_BOZP);
    TrainingType training_PO = trainingTypeService.findByAttributeUniqueResult("code", Constants.TRAINING_TYPE_PO);
    if (training_BOZP == null || training_PO == null)
      throw new RuntimeException("Some TrainingType is missing!");

    // ##############################################
    // TRAINING TYPES
    // ##############################################
    TrainingType training_pily = trainingTypeService.mergeUnique("code", "PILY", new TrainingType("PILY", "Pily a křovinořezy", "Školení - Pily a křovinořezy", null, yearsToSeconds(1)));
    TrainingType training_plosiny = trainingTypeService.mergeUnique("code", "PLOSINY", new TrainingType("PLOSINY", "Plošiny", "Školení - Plošiny", "Průkaz obsluhy plošin", yearsToSeconds(2)));
    TrainingType training_strojnici = trainingTypeService.mergeUnique("code", "STROJNICI", new TrainingType("STROJNICI", "Strojníci", "Školení - Strojníci", "Strojnický průkaz", yearsToSeconds(1)));
    TrainingType training_ridici_normal = trainingTypeService.mergeUnique("code", "RIDICI_NORMAL", new TrainingType("RIDICI_NORMAL", "Řidiči referenti", "Školení - Řidiči referenti", "Průkaz na referentká vozidla", yearsToSeconds(1)));
    TrainingType training_zahr_mistri = trainingTypeService.mergeUnique("code", "ZAHR_MISTRI", new TrainingType("ZAHR_MISTRI", "Zahradničtí mistři", "Školení - Zahradničtí mistři", null, yearsToSeconds(3)));
    TrainingType training_ridici_profi = trainingTypeService.mergeUnique("code", "RIDICI_PROFI", new TrainingType("RIDICI_PROFI", "Řidiči z povolání", "Školení - Řidiči z povolání", "Profesní průkaz", yearsToSeconds(1)));
    TrainingType training_voziky = trainingTypeService.mergeUnique("code", "VOZIKY", new TrainingType("VOZIKY", "Vysokozdvižné vozíky", "Školení - Vysokozdvižné vozíky", "Průkaz obsluhy na vysokozdvižné vozíky", yearsToSeconds(2)));

    // ##############################################
    // ROLE TYPES
    // ##############################################

    // TRAINING TYPES - roleRidicProfi
    RoleType roleRidicProfi = new RoleType(Constants.ROLETYPE_CODE_RIDIC_PROFI, "Ridič profesionál", "Ridic z povolani");
    roleRidicProfi.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_BOZP, yearsToSeconds(1))));
    roleRidicProfi.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_PO, yearsToSeconds(1))));
    roleRidicProfi.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_ridici_profi, yearsToSeconds(1))));
    // MEDICAL EXAMINATION TYPES - roleRidicProfi
    roleRidicProfi.addMedicalExaminationTypeForRoleType(medicalExaminationTypeForRoleTypeService.merge(new MedicalExaminationTypeForRoleType(medExam_Praktik, yearsToSeconds(1))));
    roleRidicProfi.addMedicalExaminationTypeForRoleType(medicalExaminationTypeForRoleTypeService.merge(new MedicalExaminationTypeForRoleType(medExam_Ocni, yearsToSeconds(1))));
    roleRidicProfi.addMedicalExaminationTypeForRoleType(medicalExaminationTypeForRoleTypeService.merge(new MedicalExaminationTypeForRoleType(medExam_Neurolog, yearsToSeconds(0))));
    roleRidicProfi.addMedicalExaminationTypeForRoleType(medicalExaminationTypeForRoleTypeService.merge(new MedicalExaminationTypeForRoleType(medExam_Psycholog, yearsToSeconds(0))));
    roleTypeService.mergeUnique("code", Constants.ROLETYPE_CODE_RIDIC_PROFI, roleRidicProfi);


    // TRAINING TYPES - roleZahradnickyMistr
    RoleType roleZahradnickyMistr = new RoleType(Constants.ROLETYPE_CODE_ZAHR_MISTR, "Zahradnický mistr", "Zahradnicky mistr");
    roleZahradnickyMistr.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_BOZP, yearsToSeconds(1))));
    roleZahradnickyMistr.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_PO, yearsToSeconds(1))));
    roleZahradnickyMistr.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_ridici_normal, yearsToSeconds(1))));
    roleZahradnickyMistr.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_zahr_mistri, yearsToSeconds(1))));
    // MEDICAL EXAMINATION TYPES - roleZahradnickyMistr
    roleZahradnickyMistr.addMedicalExaminationTypeForRoleType(medicalExaminationTypeForRoleTypeService.merge(new MedicalExaminationTypeForRoleType(medExam_Praktik, yearsToSeconds(1))));
    roleZahradnickyMistr = roleTypeService.mergeUnique("code", Constants.ROLETYPE_CODE_ZAHR_MISTR, roleZahradnickyMistr);

    // TRAINING TYPES - roleZahradnik
    RoleType roleZahradnik = new RoleType(Constants.ROLETYPE_CODE_ZAHRADNIK, "Zahradník", "Zahradnik");
    roleZahradnik.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_BOZP, yearsToSeconds(1))));
    roleZahradnik.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_PO, yearsToSeconds(1))));
    roleZahradnik.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_pily, yearsToSeconds(1))));
    // MEDICAL EXAMINATION TYPES - roleZahradnik
    roleZahradnik.addMedicalExaminationTypeForRoleType(medicalExaminationTypeForRoleTypeService.merge(new MedicalExaminationTypeForRoleType(medExam_Praktik, yearsToSeconds(1))));
    roleZahradnik = roleTypeService.mergeUnique("code", Constants.ROLETYPE_CODE_ZAHRADNIK, roleZahradnik);

    // TRAINING TYPES - roleDelnik
    RoleType roleDelnik = new RoleType(Constants.ROLETYPE_CODE_DELNIK, "Dělník", "Delnik");
    roleDelnik.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_BOZP, yearsToSeconds(1))));
    roleDelnik.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_PO, yearsToSeconds(1))));
    // MEDICAL EXAMINATION TYPES - roleDelnik
    roleDelnik.addMedicalExaminationTypeForRoleType(medicalExaminationTypeForRoleTypeService.merge(new MedicalExaminationTypeForRoleType(medExam_Praktik, yearsToSeconds(1))));
    roleDelnik = roleTypeService.mergeUnique("code", Constants.ROLETYPE_CODE_DELNIK, roleDelnik);

    // TRAINING TYPES - roleThp
    RoleType roleThp = new RoleType(Constants.ROLETYPE_CODE_THP, "Technicko-hospodářský pracovník", "Pracovník administrativy");
    roleThp.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_BOZP, yearsToSeconds(1))));
    roleThp.addTrainingTypeForRoleType(trainingTypeForRoleTypeService.merge(new TrainingTypeForRoleType(training_PO, yearsToSeconds(1))));
    // MEDICAL EXAMINATION TYPES - roleThp
    roleThp.addMedicalExaminationTypeForRoleType(medicalExaminationTypeForRoleTypeService.merge(new MedicalExaminationTypeForRoleType(medExam_Praktik, yearsToSeconds(3))));
    roleThp = roleTypeService.mergeUnique("code", Constants.ROLETYPE_CODE_THP, roleThp);
  }

  public void fillPeopleAndCompanies()
  {
    // ADRESA - Křižatky
    Address address1 = addressService.merge(new Address("Street 1", "City 1", "Country 1", "ZIP 1"));

    // Dagmar Stříbrná
    Employee empCermakova = new Employee(new Person("Dagmar", "Stříbrná", address1));
    empCermakova.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_THP)));
    empCermakova = employeeService.merge(empCermakova);

    // Other JENA workers
    Employee empKahlerova = new Employee(new Person("Barbora", "Kahlerová"));
    empKahlerova.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_THP)));
    empKahlerova = employeeService.merge(empKahlerova);

    Employee empSimkova = new Employee(new Person("Lucie", "Šimková"));
    empSimkova.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_THP)));
    empSimkova.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_ZAHR_MISTR)));
    empSimkova = employeeService.merge(empSimkova);

    Employee empVecer = new Employee(new Person("Aleš", "Večeř"));
    empVecer.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_RIDIC_PROFI)));
    empVecer = employeeService.merge(empVecer);

    Employee empBujnak = new Employee(new Person("Dan", "Bujňák"));
    empBujnak.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_ZAHRADNIK)));
    empBujnak = employeeService.merge(empBujnak);

    Employee empPlaz = new Employee(new Person("Miroslav", "Plaz"));
    empPlaz.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_ZAHRADNIK)));
    empPlaz = employeeService.merge(empPlaz);

    Employee empSedlackova = new Employee(new Person("Lucie", "Sedláčková"));
    empSedlackova.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_THP)));
    empSedlackova = employeeService.merge(empSedlackova);

    Employee empKormundova = new Employee(new Person("Pavla", "Kormundová"));
    empKormundova.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_THP)));
    empKormundova = employeeService.merge(empKormundova);

    Employee empPrasil = new Employee(new Person("Jaroslav", "Prášil"));
    empPrasil.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_ZAHRADNIK)));
    empPrasil = employeeService.merge(empPrasil);

    Employee empPastva = new Employee(new Person("Josef", "Pastva"));
    empPastva.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_ZAHRADNIK)));
    empPastva = employeeService.merge(empPastva);

    // JENA company
    Company jenaCompany;
    if (companyService.findByAttribute("name", "JENA").isEmpty())
    {
      jenaCompany = companyService.merge(new Company("JENA", "ICO 1", "DIC 1"));
    }
    else
    {
      jenaCompany = companyService.findByAttributeUniqueResult("name", "JENA");
    }

    Address jenaAddress = new Address("Letna XYZ", "Praha", "Czech Republic", "140 00");
    jenaAddress = addressService.merge(jenaAddress);
    jenaCompany.setBaseAddress(jenaAddress);

    jenaCompany.hireEmployee(empCermakova);
    jenaCompany.hireEmployee(empKahlerova);
    jenaCompany.hireEmployee(empSimkova);
    jenaCompany.hireEmployee(empVecer);
    jenaCompany.hireEmployee(empVecer);
    jenaCompany.hireEmployee(empPlaz);
    jenaCompany.hireEmployee(empSedlackova);
    jenaCompany.hireEmployee(empKormundova);
    jenaCompany.hireEmployee(empPrasil);
    jenaCompany.hireEmployee(empPastva);

    // Rostislav Stříbrný
    Person rosta = new Person("Rostislav", "Stříbrný", address1);
    rosta.setBirthDate(new Date());
    rosta = personService.merge(rosta);
    Employee empStribrny = new Employee(rosta);
    empStribrny.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_IT_ARCHITECT)));
    empStribrny.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_IT_CONSULTANT)));
    empStribrny = employeeService.merge(empStribrny);

    ExternalWorker extWorkerRosta = new ExternalWorker(rosta);
    extWorkerRosta.addRole(new Role(roleTypeService.findByAttributeUniqueResult("code", Constants.ROLETYPE_CODE_IT_PROGRAMMER)));
    extWorkerRosta = externalWorkerService.merge(extWorkerRosta);

    jenaCompany.hireExternalWorker(extWorkerRosta);
    jenaCompany = companyService.mergeUnique("id", jenaCompany.getId(), jenaCompany);
  }

  public MachineType[] fillMachineries()
  {
    MachineType mtOsobniAuto = machineTypeService.merge(new MachineType("Osobní auta", "Osobní automobily"));
    MachineType mtUzitkoveAuto = machineTypeService.merge(new MachineType("Užitková auta", "Užitkové automobily"));
    MachineType mtNakladniAuto = machineTypeService.merge(new MachineType("Nákladní auta", "Nákladní automobil"));
    MachineType mtPrivesy = machineTypeService.merge(new MachineType("Privesy", "Přívěsy"));
    MachineType mtTraktory = machineTypeService.merge(new MachineType("Traktory", "Traktory"));
    MachineType mtStavebniStroje = machineTypeService.merge(new MachineType("Stavební stroje", "Stavební stroje"));
    MachineType mtZemedelskeStroje = machineTypeService.merge(new MachineType("Zemědělské stroje", "Zemědělské stroje"));

    MachineType mtPily = machineTypeService.merge(new MachineType("Pily", "Pily"));
    MachineType mtKrovinorezy = machineTypeService.merge(new MachineType("Křovinořezy", "Křovinořezy"));
    MachineType mtFukary = machineTypeService.merge(new MachineType("Fukary", "Fukary"));
    MachineType mtPlosiny = machineTypeService.merge(new MachineType("Plošiny", "Plošiny"));
    MachineType mtVysokoVoziky = machineTypeService.merge(new MachineType("Vysokozdvižné vozíky", "Vysokozdvižné vozíky"));
    MachineType mtSekacky = machineTypeService.merge(new MachineType("Sekačky", "Sekačky"));

    MachineType genTypes[] = new MachineType[]{mtOsobniAuto, mtUzitkoveAuto, mtNakladniAuto, mtNakladniAuto, mtPrivesy, mtTraktory, mtStavebniStroje, mtZemedelskeStroje, mtPily, mtKrovinorezy, mtFukary, mtPlosiny, mtVysokoVoziky, mtSekacky};
    return genTypes;
  }

  public void fillRandomMachinery(MachineType[] genTypes)
  {
    Company jenaCompany = companyService.findByAttributeUniqueResult("name", "JENA");
    if (jenaCompany == null)
      throw new RuntimeException("JENA company does not exists!");

    prepareSharedData.fillRandomMachinery(jenaCompany, genTypes);
  }
}
